package com.yyc.springtransactional.test.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.yyc.springtransactional.test.entity.TBusPersonalDetails;
import com.yyc.springtransactional.test.entity.TBusUser;
import com.yyc.springtransactional.test.local.UserLocal;
import com.yyc.springtransactional.test.mapper.TBusUserMapper;
import com.yyc.springtransactional.test.service.ITBusPersonalDetailsService;
import com.yyc.springtransactional.test.service.ITBusUserService;
import lombok.AllArgsConstructor;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Description: 用户履历表
 * @Author: 杨艺聪
 * @Date:   2020-06-06
 * @Version: V1.0
 */
@Service
@AllArgsConstructor
public class TBusUserServiceImpl extends ServiceImpl<TBusUserMapper, TBusUser> implements ITBusUserService {

    private ITBusPersonalDetailsService busPersonalDetailsService;

    private DataSourceTransactionManager dataSourceTransactionManager;

    private TransactionDefinition transactionDefinition;

    /**
     * A -> B
     * A没有事务
     * B没有事务
     */
    @Override
    public void withoutTX() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.withoutTX();
        //int i=1/0;
    }

    /**
     * A -> B
     * A 有事务/没事务
     * B @Transactional(propagation= Propagation.REQUIRED)
     */
    @Override
    //@Transactional
    @Transactional
    public void required() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.required();
        //int i =1/0;
    }

    /**
     * A -> B
     * 白话: 以A为准，A有就都有、A没有就都没有
     * A 有事务/没事务
     * B @Transactional(propagation= Propagation.SUPPORTS)
     * 如果当前有事务，则加入这个事务，即：A、B共用一个事务
     * 如果当前没事务，则不支持事务，  即：A、B没有事务
     */
    @Override
    //@Transactional
    @Transactional
    public void supports() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.supports();
        //int i =1/0;
    }

    /**
     * A -> B
     * 白话: 必须有事务，否则报错
     * A 有事务/没事务
     * B @Transactional(propagation= Propagation.mandtory)
     */
    @Override
    //@Transactional
    @Transactional
    public void mandtory() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.mandtory();
        //int i =1/0;
    }

    /**
     * A -> B
     * 白话: 不管A有没有事务，B都新建事务
     * A 有事务/没事务
     * B @Transactional(propagation= Propagation.REQUIRES_NEW)
     * 如果当前有事务，则新建一个事务，即：A、B各管个的事务
     * 如果当前没事务，则新建一个事务，  即：A没有事务，B有事务
     */
    @Override
    //@Transactional
    @Transactional
    public void requiresNew() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.requiresNew();
        int i =1/0;
    }

    /**
     * A -> B
     * 白话: A有事务就挂起，没有就算了，反正保证B没有事务
     * A 有事务/没事务
     * B @Transactional(propagation= Propagation.NOT_SUPPORTED)
     * 如果当前有事务，则挂起，即：A、B都没有事务
     * 如果当前没事务，则不管，  即：A事务挂起，B没事务
     */
    @Override
    //@Transactional
    @Transactional
    public void notSupport() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.notSupport();
        //int i =1/0;
    }

    /**
     * A -> B
     * 白话: 必须没有事务，否则报错
     * A 有事务/没事务
     * B @Transactional(propagation= Propagation.NEVER)
     */
    @Override
    //@Transactional
    @Transactional
    public void never() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.never();
        //int i =1/0;
    }

    /**
     * A -> B
     * 白话: A有事务,则B用嵌套事务。A没有事务则B新建任务
     * A 有事务/没事务
     * B @Transactional(propagation= Propagation.NESTED)
     */
    @Override
    //@Transactional
    @Transactional
    public void nested() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.nested();
        int i =1/0;
    }

    /**
     * A -> B
     * A @Transactional()
     * B 编程式事务 DataSourceTransactionManager
     */
    @Override
    //@Transactional
    @Transactional
    public void byHand() {
        TBusUser user = this.getUser();
        this.insert(user);
        busPersonalDetailsService.byHand();
        //int i =1/0;
    }

    /**
     * A -> B
     * B 编程式事务 DataSourceTransactionManager
     */
    @Override
    public void byHand2() {
        // 手动开启事务
        TransactionStatus transaction = null;
        try {
            transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);
            this.insert(getUser());
            // 手动提交事务
            busPersonalDetailsService.byHand();
            dataSourceTransactionManager.commit(transaction);
            //busPersonalDetailsService.byHand();
        } catch (Exception e) {
            // 手动回滚事务
            if (transaction != null) {
                dataSourceTransactionManager.rollback(transaction);
            }
            return;
        }
    }


    /**
     * 虚构一个用户对象
     * @return
     */
    private TBusUser getUser(){
        TBusUser user = new TBusUser();
        String id = IdUtil.simpleUUID();
        user.setId(id);
        user.setUsername("yyc");
        UserLocal.userIdLocal.set(id);
        return user;
    }

}
